/**
 * 浏览器兼容性Polyfill模块
 * 为不支持现代Web API的浏览器提供兼容性支持
 * @module polyfills
 */

/**
 * 初始化所有必要的polyfill
 * 确保游戏在各种浏览器环境中都能正常运行
 * @example
 * import { initializePolyfills } from '@/utils/polyfills';
 * initializePolyfills();
 */
export function initializePolyfills(): void {
  console.log('开始应用浏览器兼容性polyfill...')
  
  // 应用各种polyfill
  polyfillRequestAnimationFrame()
  polyfillPerformanceNow()
  polyfillAudioContext()
  polyfillCanvas2D()
  polyfillLocalStorage()
  polyfillCustomEvents()
  polyfillIntersectionObserver()
  polyfillResizeObserver()
  
  console.log('浏览器兼容性polyfill应用完成')
}

/**
 * RequestAnimationFrame polyfill
 * 为不支持requestAnimationFrame的浏览器提供兼容性
 */
function polyfillRequestAnimationFrame(): void {
  if (!window.requestAnimationFrame) {
    console.log('应用 requestAnimationFrame polyfill')
    
    let lastTime = 0
    window.requestAnimationFrame = function(callback: FrameRequestCallback): number {
      const currTime = new Date().getTime()
      const timeToCall = Math.max(0, 16 - (currTime - lastTime))
      const id = window.setTimeout(() => {
        callback(currTime + timeToCall)
      }, timeToCall)
      lastTime = currTime + timeToCall
      return id
    }
  }

  if (!window.cancelAnimationFrame) {
    window.cancelAnimationFrame = function(id: number): void {
      clearTimeout(id)
    }
  }
}

/**
 * Performance.now() polyfill
 * 为不支持高精度时间戳的浏览器提供兼容性
 */
function polyfillPerformanceNow(): void {
  if (!window.performance) {
    console.log('应用 performance polyfill')
    window.performance = {} as Performance
  }

  if (!window.performance.now) {
    const navigationStart = window.performance.timing?.navigationStart || Date.now()
    window.performance.now = function(): number {
      return Date.now() - navigationStart
    }
  }
}

/**
 * AudioContext polyfill
 * 为不同浏览器的AudioContext实现提供统一接口
 */
function polyfillAudioContext(): void {
  if (!window.AudioContext && (window as any).webkitAudioContext) {
    console.log('应用 AudioContext polyfill (webkit)')
    window.AudioContext = (window as any).webkitAudioContext
  }
  
  // 为旧版本浏览器添加AudioContext方法polyfill
  if (window.AudioContext) {
    const AudioContextPrototype = window.AudioContext.prototype
    
    // createGain polyfill
    if (!AudioContextPrototype.createGain && (AudioContextPrototype as any).createGainNode) {
      AudioContextPrototype.createGain = (AudioContextPrototype as any).createGainNode
    }
    
    // createDelay polyfill
    if (!AudioContextPrototype.createDelay && (AudioContextPrototype as any).createDelayNode) {
      AudioContextPrototype.createDelay = (AudioContextPrototype as any).createDelayNode
    }
    
    // createScriptProcessor polyfill
    if (!AudioContextPrototype.createScriptProcessor && (AudioContextPrototype as any).createJavaScriptNode) {
      AudioContextPrototype.createScriptProcessor = (AudioContextPrototype as any).createJavaScriptNode
    }
  }
}

/**
 * Canvas 2D Context polyfill
 * 为Canvas 2D API添加缺失的方法和属性
 */
function polyfillCanvas2D(): void {
  if (typeof CanvasRenderingContext2D !== 'undefined') {
    const ctx2DPrototype = CanvasRenderingContext2D.prototype
    
    // ellipse方法polyfill (IE不支持)
    if (!ctx2DPrototype.ellipse) {
      console.log('应用 Canvas ellipse polyfill')
      ctx2DPrototype.ellipse = function(
        x: number, y: number, 
        radiusX: number, radiusY: number, 
        rotation: number, 
        startAngle: number, endAngle: number, 
        anticlockwise?: boolean
      ): void {
        this.save()
        this.translate(x, y)
        this.rotate(rotation)
        this.scale(radiusX, radiusY)
        this.arc(0, 0, 1, startAngle, endAngle, anticlockwise)
        this.restore()
      }
    }
    
    // resetTransform方法polyfill
    if (!ctx2DPrototype.resetTransform) {
      console.log('应用 Canvas resetTransform polyfill')
      ctx2DPrototype.resetTransform = function(): void {
        this.setTransform(1, 0, 0, 1, 0, 0)
      }
    }
    
    // imageSmoothingEnabled属性polyfill
    if (ctx2DPrototype.imageSmoothingEnabled === undefined) {
      Object.defineProperty(ctx2DPrototype, 'imageSmoothingEnabled', {
        get: function() {
          return (this as any).webkitImageSmoothingEnabled || 
                 (this as any).mozImageSmoothingEnabled || 
                 (this as any).msImageSmoothingEnabled || true
        },
        set: function(value: boolean) {
          (this as any).webkitImageSmoothingEnabled = value;
          (this as any).mozImageSmoothingEnabled = value;
          (this as any).msImageSmoothingEnabled = value
        }
      })
    }
  }
}

/**
 * LocalStorage polyfill
 * 为不支持localStorage的环境提供内存存储替代方案
 */
function polyfillLocalStorage(): void {
  try {
    // 测试localStorage是否可用
    const test = '__localStorage_test__'
    window.localStorage.setItem(test, test)
    window.localStorage.removeItem(test)
  } catch (e) {
    console.log('应用 localStorage polyfill')
    
    const memoryStorage: { [key: string]: string } = {}
    
    const mockStorage = {
      getItem: (key: string): string | null => {
        return memoryStorage[key] || null
      },
      setItem: (key: string, value: string): void => {
        memoryStorage[key] = String(value)
      },
      removeItem: (key: string): void => {
        delete memoryStorage[key]
      },
      clear: (): void => {
        Object.keys(memoryStorage).forEach(key => delete memoryStorage[key])
      },
      get length(): number {
        return Object.keys(memoryStorage).length
      },
      key: (index: number): string | null => {
        const keys = Object.keys(memoryStorage)
        return keys[index] || null
      }
    }
    
    try {
      Object.defineProperty(window, 'localStorage', {
        value: mockStorage,
        writable: false,
        configurable: true
      })
    } catch (defineError) {
      // 如果无法重新定义，直接赋值
      ;(window as any).localStorage = mockStorage
    }
  }
}

/**
 * CustomEvent polyfill
 * 为IE浏览器提供CustomEvent构造函数支持
 */
function polyfillCustomEvents(): void {
  if (typeof window.CustomEvent !== 'function') {
    console.log('应用 CustomEvent polyfill')
    
    function CustomEvent(event: string, params?: CustomEventInit): CustomEvent {
      const evt = document.createEvent('CustomEvent')
      evt.initCustomEvent(
        event,
        params?.bubbles || false,
        params?.cancelable || false,
        params?.detail || null
      )
      return evt
    }
    
    window.CustomEvent = CustomEvent as any
  }
}

/**
 * IntersectionObserver polyfill
 * 为不支持IntersectionObserver的浏览器提供基础实现
 */
function polyfillIntersectionObserver(): void {
  if (!window.IntersectionObserver) {
    console.log('应用 IntersectionObserver polyfill')
    
    class IntersectionObserverPolyfill {
      private callback: IntersectionObserverCallback
      private options: IntersectionObserverInit
      private targets: Element[] = []
      private intervalId: number | null = null
      
      constructor(callback: IntersectionObserverCallback, options: IntersectionObserverInit = {}) {
        this.callback = callback
        this.options = {
          root: options.root || null,
          rootMargin: options.rootMargin || '0px',
          threshold: options.threshold || 0
        }
      }
      
      observe(target: Element): void {
        if (!this.targets.includes(target)) {
          this.targets.push(target)
          this.startObserving()
        }
      }
      
      unobserve(target: Element): void {
        const index = this.targets.indexOf(target)
        if (index > -1) {
          this.targets.splice(index, 1)
          if (this.targets.length === 0) {
            this.stopObserving()
          }
        }
      }
      
      disconnect(): void {
        this.targets = []
        this.stopObserving()
      }
      
      private startObserving(): void {
        if (this.intervalId === null) {
          this.intervalId = window.setInterval(() => {
            this.checkIntersections()
          }, 100)
        }
      }
      
      private stopObserving(): void {
        if (this.intervalId !== null) {
          clearInterval(this.intervalId)
          this.intervalId = null
        }
      }
      
      private checkIntersections(): void {
        const entries: IntersectionObserverEntry[] = this.targets.map(target => {
          const rect = target.getBoundingClientRect()
          const isIntersecting = rect.top < window.innerHeight && rect.bottom > 0
          
          return {
            target,
            isIntersecting,
            intersectionRatio: isIntersecting ? 1 : 0,
            boundingClientRect: rect,
            intersectionRect: isIntersecting ? rect : new DOMRect(),
            rootBounds: new DOMRect(0, 0, window.innerWidth, window.innerHeight),
            time: performance.now()
          } as IntersectionObserverEntry
        })
        
        if (entries.length > 0) {
          this.callback(entries, this as any)
        }
      }
    }
    
    window.IntersectionObserver = IntersectionObserverPolyfill as any
  }
}

/**
 * ResizeObserver polyfill
 * 为不支持ResizeObserver的浏览器提供基础实现
 */
function polyfillResizeObserver(): void {
  if (!window.ResizeObserver) {
    console.log('应用 ResizeObserver polyfill')
    
    class ResizeObserverPolyfill {
      private callback: ResizeObserverCallback
      private targets: Element[] = []
      private intervalId: number | null = null
      private lastSizes = new Map<Element, { width: number; height: number }>()
      
      constructor(callback: ResizeObserverCallback) {
        this.callback = callback
      }
      
      observe(target: Element): void {
        if (!this.targets.includes(target)) {
          this.targets.push(target)
          const rect = target.getBoundingClientRect()
          this.lastSizes.set(target, { width: rect.width, height: rect.height })
          this.startObserving()
        }
      }
      
      unobserve(target: Element): void {
        const index = this.targets.indexOf(target)
        if (index > -1) {
          this.targets.splice(index, 1)
          this.lastSizes.delete(target)
          if (this.targets.length === 0) {
            this.stopObserving()
          }
        }
      }
      
      disconnect(): void {
        this.targets = []
        this.lastSizes.clear()
        this.stopObserving()
      }
      
      private startObserving(): void {
        if (this.intervalId === null) {
          this.intervalId = window.setInterval(() => {
            this.checkResize()
          }, 100)
        }
      }
      
      private stopObserving(): void {
        if (this.intervalId !== null) {
          clearInterval(this.intervalId)
          this.intervalId = null
        }
      }
      
      private checkResize(): void {
        const entries: ResizeObserverEntry[] = []
        
        this.targets.forEach(target => {
          const rect = target.getBoundingClientRect()
          const lastSize = this.lastSizes.get(target)
          
          if (!lastSize || lastSize.width !== rect.width || lastSize.height !== rect.height) {
            this.lastSizes.set(target, { width: rect.width, height: rect.height })
            
            entries.push({
              target,
              contentRect: new DOMRect(0, 0, rect.width, rect.height),
              borderBoxSize: [{ blockSize: rect.height, inlineSize: rect.width }],
              contentBoxSize: [{ blockSize: rect.height, inlineSize: rect.width }],
              devicePixelContentBoxSize: [{ blockSize: rect.height, inlineSize: rect.width }]
            } as ResizeObserverEntry)
          }
        })
        
        if (entries.length > 0) {
          this.callback(entries, this as any)
        }
      }
    }
    
    window.ResizeObserver = ResizeObserverPolyfill as any
  }
}

/**
 * 检查特定API是否需要polyfill
 * @param apiName - API名称
 * @returns 是否需要polyfill
 */
export function needsPolyfill(apiName: string): boolean {
  switch (apiName) {
    case 'requestAnimationFrame':
      return !window.requestAnimationFrame
    case 'performance':
      return !window.performance || !window.performance.now
    case 'AudioContext':
      return !window.AudioContext && !(window as any).webkitAudioContext
    case 'localStorage':
      try {
        const test = '__localStorage_test__'
        window.localStorage.setItem(test, test)
        window.localStorage.removeItem(test)
        return false
      } catch {
        return true
      }
    case 'CustomEvent':
      return typeof window.CustomEvent !== 'function'
    case 'IntersectionObserver':
      return !window.IntersectionObserver
    case 'ResizeObserver':
      return !window.ResizeObserver
    default:
      return false
  }
}

/**
 * 获取所有需要polyfill的API列表
 * @returns 需要polyfill的API名称数组
 */
export function getRequiredPolyfills(): string[] {
  const apis = [
    'requestAnimationFrame',
    'performance',
    'AudioContext',
    'localStorage',
    'CustomEvent',
    'IntersectionObserver',
    'ResizeObserver'
  ]
  
  return apis.filter(api => needsPolyfill(api))
}